home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Essentials / MacApp Documentation / MacApp AppleLink Messages / MacApp.Tech$ May 89 / U0008-More on "Later Vers-May89 < prev    next >
Encoding:
Text File  |  1989-06-26  |  5.5 KB  |  164 lines  |  [TEXT/GEOL]

  1. Item    3002379                         4-May-89        23:06
  2.  
  3. From:   CH0095                          CH DEV PEMD Group
  4.  
  5. To:     MACAPP.TECH$                    MACAPP Tech
  6.  
  7. Sub:    More on "Later Versions"
  8.  
  9. Hi Everyone,
  10.  
  11. Thanks for the great communal response to the "Later Versions" questions.  It's
  12. still not entirely clear to me.
  13.  
  14. Assume that DoRead/doWrite use
  15.      GraphRecord =
  16.           DataArray:     Array[1...kMaxPoints] of String[kMaxDataLength};
  17.           PredictArray:  Array[1...kMaxPoints] of Boolean;
  18.           AreaName:      String[kMaxAreaNameLength];
  19.           AreaName:      String[kMaxAbbrevLength];
  20.           PrtedictInfo:  String[kMaxPredictInfoLength];
  21.      End;  {all identifiers begiining with "k" are constants defined in the
  22. CONST section of ourApp.p.}
  23.  
  24. There is a TGraphObject that corresponds to the GraphRecord.  It has the
  25. identical data structure plus methods.  At read time the fields of the
  26. GraphRecords are read into the fields of GraphObjects. If different
  27. GraphRecords are defined for different values of the "k" constants (e.g.
  28. GraphRecord1, GraphRecord2, etc.) then there must be correspondingly different
  29. definitions for  TGraphObjects (e.g. TGraphObject1, TGraphObject2, etc.).
  30.  
  31. Subsequent code must then always consider which GraphObject definition is to be
  32. used.  For example, whenever a New call is made there must be some sort of
  33. conditional statement determining the type of GraphObject to make, and then all
  34. following code must be duplicated for each type of GraphObject.
  35.  
  36. Am I off?  If accurate such a strategy would result is extremely thick and
  37. ponderous code.  There seems to be two problems.  All would be straight forward
  38. if Pascal allowed dynamic arrays and second it would also work if the
  39. GraphRecord and GraphObject definitions could be kept seperate.
  40.  
  41. Below is a link from MacDTS keeping the two definitions seperate.  I'm not yet
  42. clear on how to implement it.  The first problem is that I don't understand an
  43. array defintion as:  Array [0..0] of INTEGER;  how can an array dimension have
  44. no length?  Is his Arraytemplate an indirect way to establish dynamic arrays in
  45. Pascal?
  46.  
  47. Am I thinking about all this in a funny way?  Wiil really appreciate whatever
  48. guidance any of you have.
  49.  
  50. Regards,
  51. Ernie
  52.  
  53.  
  54. _____________________________________________________________________________
  55. The only clean way to make your file formats the same while
  56. your internal data structures change is to seperate the
  57. file format data structures from the class structures.
  58.  
  59. You should define a set of RECORD templates for your file
  60. format, and have your objects write their data in the
  61. format of the templates. This means that you have to do
  62. more programming work, but it does give you some valuable
  63. independence from your object definitions. Whatever file
  64. format you do pick, it should be smart enough to deal with
  65. variable length data.
  66.  
  67. There isn't any way that Pascal (or C) can be made to
  68. understand dynamic, variably sized data structures. The
  69. language just doesn't work that way.
  70.  
  71. Here is a small example. I'm just typing this in out of my
  72. head, so there will probably be a few typos and type
  73. checking errors, but you get the idea. Lets say I have a
  74. class, TMyData:
  75.  
  76. CONST
  77.    kNumPoints = 24;
  78.  
  79. TYPE
  80.    TMyData = OBJECT(TObject)
  81.    fMyArray : ARRAY[1..kNumPoints] OF INTEGER;
  82.    { all the usual methods...}
  83.    { our I/O methods, called by our subclass of TDocument...}
  84.    TMyData.DoRead(aRefNum: INTEGER);
  85.    TMyData.DoWrite(aRefNum: INTEGER);
  86.    END;
  87.  
  88.    { Template for our array type }
  89.    MyArrayTemplate = RECORD
  90.    arraySize : INTEGER;
  91.    arrayData : ARRAY [0..0] OF INTEGER;
  92.    END;
  93.    MyArrayTemplatePtr = ^MyArrayTemplate;
  94.    MyArrayTemplateHdl = ^MyArrayTemplatePtr;
  95.  
  96. Now, in my DoWrite method, I do this:
  97.  
  98. PROCEDURE TMyData.DoWrite(aRefNum:INTEGER);
  99. VAR
  100.    arrTmpl : MyArrayTemplateHdl;
  101.    i, nElems : INTEGER;
  102.    tmplSize : LONGINT;
  103. BEGIN
  104.    { allocate a template of correct size }
  105.    tmplSize := SIZEOF(MyArrayTemplate) + (SIZEOF(INTEGER) * kNumPoints);
  106.    arrTmpl = NewHandle(tmplSize);
  107.    FailNIL(arrTmpl);
  108.    { fill in the template }
  109.    arrTmpl^^.arraySize := kNumPoints;
  110.    {$PUSH} {$R-}
  111.    FOR i := 0 to kNumPoints-1 DO
  112.      arrTmpl^^.arrayData[i] := fMyArray[i+1];
  113.    {$POP}
  114.    { Write size of array }
  115.    nElems := kNumPoints;
  116.    i := SIZEOF(INTEGER);
  117.    FailOSErr(FSWrite(aRefNum,i,Ptr(@nElems));
  118.    { Write contents of array }
  119.    FailOSErr(FSWrite(aRefNum,tmplSize,Ptr(arrTmpl^));
  120. END;
  121.  
  122. Now, DoRead has to read in a data structure, which may be bigger than
  123. the current size...
  124.  
  125. PROCEDURE TMyData.DoRead(aRefNum:INTEGER);
  126. VAR
  127.    arrTmpl : MyArrayTemplateHdl;
  128.    i,cnt : INTEGER;
  129.    tmplSize, nElems : INTEGER;
  130. BEGIN
  131.    { Read num elems in array }
  132.    cnt := SIZEOF(INTEGER);
  133.    FailOSErr(FSRead(aRefNum,cnt,Ptr(@nElems)));
  134.    { allocate a template big enough to read entire array }
  135.    tmplSize := SIZEOF(MyArrayTemplate) + (SIZEOF(INTEGER) * nElems);
  136.    arrTmpl = NewHandle(tmplSize);
  137.    FailNIL(arrTmpl);
  138.    { Read array into template }
  139.    cnt := SIZEOF(INTEGER) * nElems;
  140.    FailOSErr(FSRead(aRefNum,cnt,Ptr(@arrTmpl^^.arrayData)));
  141.    { now, copy the array into our object }
  142.    cnt := MIN(kNumPoints,nElems);  { don't try and copy more than we got }
  143.    {$PUSH} {$R-}
  144.    FOR i := 0 TO cnt-1 DO
  145.      fMyArray[i+1] := arrTmpl^^.arrayData[i];
  146.    { If we don't have enough data to fill object array, pad with zeros }
  147.    IF nElems < kNumPoints THEN
  148.      FOR i := cnt TO kNumPoints DO
  149.    fMyArray[i] := 0;
  150.    { NOTE: we truncate array if it was too big... }
  151.    {$POP}
  152. END;
  153.  
  154. Have fun,
  155.  
  156. Andrew Shebanow
  157. MacDTS
  158. Apple Computer, Inc.
  159.  
  160.  
  161.  
  162.  
  163.  
  164.